﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Net;
using System.Threading;
using System.Xml;
using System.Collections.Concurrent;
using HtmlAgilityPack;

namespace RelatedWordsWCFService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                 ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class RelatedWordsWCFService : IRelatedWordsWCFService
    {
        const int NUMBER_OF_WORDS_TO_RETURN = 10;

        public string[] getRelatedWordsFromAddress(string word, Uri url)
        {
            string websiteContent = getWebContent(url.ToString());
            string parsedContent = parseString(websiteContent);
            return getRelatedWords(word, parsedContent);
        }

        public string[] getRelatedWords(string word, string stuffToLookIn)
        {
            string[] relatedWords = null;
            TextGroup group = new TextGroup(stuffToLookIn);
            var relatedWordsAndWeights = group.getRelatedWordsAndWeights(word);
            relatedWords = getTopWords(relatedWordsAndWeights);
            return relatedWords;
        }

        private string getWebContent(string url)
        {
            HtmlContent content = new HtmlContent(new Uri(url));
            return content.getContent();
        }

        private string parseString(string str)
        {
            WordFilterService.WordFilterWCFServiceClient client =
                new WordFilterService.WordFilterWCFServiceClient();
            string parsedString = client.WordFilter(str);
            client.Close();
            return parsedString;
        }

        private string[] getTopWords<T, U>(Dictionary<T, U> similarWordsAndWeights) where U : IComparable
        {
            var myList = similarWordsAndWeights.ToList();

            myList.Sort((firstPair, nextPair) =>
            {
                return -firstPair.Value.CompareTo(nextPair.Value);
            }
            );
            var dictionary = myList.ToDictionary((keyItem) => keyItem.Key, (valueItem) => valueItem.Value);
            if (similarWordsAndWeights.Count < NUMBER_OF_WORDS_TO_RETURN)
            {
                return createStringArrayFromGenericList(dictionary.Keys.ToList().GetRange(0, similarWordsAndWeights.Count));
            }
            return createStringArrayFromGenericList(dictionary.Keys.ToList().GetRange(0, NUMBER_OF_WORDS_TO_RETURN));
        }

        private string[] createStringArrayFromGenericList<T>(List<T> list)
        {
            string[] output = new string[list.Count()];
            int i = 0;
            foreach (T item in list)
            {
                output[i] = item.ToString();
                i++;
            }
            return output;
        }
    }

    /// <summary>
    /// Class to download html contents instead of using the remote service.
    /// </summary>
    public class HtmlContent
    {
        string html = "";

        public HtmlContent(Uri location)
        {
            startHtmlDownload(location);
        }

        public void startHtmlDownload(Uri location)
        {
            WebClient client = new WebClient();
            client.DownloadStringCompleted +=
                new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
            client.DownloadStringAsync(location);
        }

        private void client_DownloadStringCompleted(object sender,
                                            DownloadStringCompletedEventArgs e)
        {
            try
            {
               html = e.Result;
            } catch (Exception exception){
                html = "-01";
            }
        }

        public string getContent()
        {
            while (html.Equals(""))
            {
                Thread.Sleep(10);
            }
            return html;
        }
    }
}
